package com.xy.bizportdemo;

import android.app.Activity;
import android.app.Application;
import android.app.Instrumentation;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.os.Bundle;
import android.os.IBinder;
import android.util.Log;

import com.xy.bizportdemo.controller.PluginManager;

import java.lang.reflect.Field;
import java.lang.reflect.Method;

/**
 * Created by admin on 2017/10/13 0013.
 */

public class InstrumentationWrapper extends Instrumentation {
    private static final String TAG = "InstrumentationWrapper";
    private static final String CLASSNAME_WEB = "com.xy.bizportdemo.StubNearbyPointList";//"cn.cmcc.online.smsapi.ui.web.SdkWebActivity";
    Instrumentation mBase = null;

    public static void replaceInstrumentation(Activity activity) {
        try {
            Field field = Activity.class.getDeclaredField("mInstrumentation");
            field.setAccessible(true);
            Instrumentation instrumentation = (Instrumentation) field.get(activity);
            Instrumentation proxy = new InstrumentationWrapper(instrumentation);
            field.set(activity, proxy);
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        }

    }

    public static void replaceInstrumentation() {
        try {
            Class<?> activityThreadClass = Class.forName("android.app.ActivityThread");
            Method currentActivityThreadMethod = activityThreadClass.getDeclaredMethod("currentActivityThread");
            currentActivityThreadMethod.setAccessible(true);
            //currentActivityThread是一个static函数所以可以直接invoke，不需要带实例参数
            Object currentActivityThread = currentActivityThreadMethod.invoke(null);
            Field instrumentationField = activityThreadClass.getDeclaredField("mInstrumentation");
            instrumentationField.setAccessible(true);
            Instrumentation instrumentation = (Instrumentation) instrumentationField.get(currentActivityThread);
            Instrumentation proxy = new InstrumentationWrapper(instrumentation);
            instrumentationField.set(currentActivityThread, proxy);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public InstrumentationWrapper(Instrumentation base) {
        mBase = base;
    }

    public ActivityResult execStartActivity(
            Context who, IBinder contextThread, IBinder token, Activity target,
            Intent intent, int requestCode, Bundle options) {
        Log.i(TAG, "execStartActivity: " + intent + intent.getComponent());
        intent.setClassName(who, "com.xy.bizportdemo.StubSdkWebActivity");
        try {
            Method execStartActivity = Instrumentation.class.getDeclaredMethod(
                    "execStartActivity",
                    Context.class,
                    IBinder.class,
                    IBinder.class,
                    Activity.class,
                    Intent.class,
                    int.class,
                    Bundle.class);
            execStartActivity.setAccessible(true);
            return (ActivityResult) execStartActivity.invoke(mBase, who,
                    contextThread, token, target, intent, requestCode, options);
        } catch (Exception e) {
            e.printStackTrace();
        }

        return null;
    }

    private String getRealClassName(String className, Intent intent) {
        return CLASSNAME_WEB;
    }

    @Override
    public Activity newActivity(ClassLoader cl, String className, Intent intent) throws InstantiationException, IllegalAccessException,
            ClassNotFoundException {
        Log.i(TAG, "newActivity: short className" + className + "intent:" + intent);
        String newClassName = getRealClassName(className, intent);
        //return mBase.newActivity(PluginManager.getInstance().getPluginContext().getClassLoader(), newClassName, intent);
        return mBase.newActivity(cl, newClassName, intent);
    }

    @Override
    public Activity newActivity(Class<?> clazz, Context context,
                                IBinder token, Application application, Intent intent, ActivityInfo info,
                                CharSequence title, Activity parent, String id,
                                Object lastNonConfigurationInstance) throws InstantiationException,
            IllegalAccessException {
        Log.i(TAG, "newActivity: className" + clazz.getCanonicalName());
        return mBase.newActivity(clazz, context, token, application, intent, info, title, parent, id, lastNonConfigurationInstance);
    }
}
